<?php


namespace app\api\controller\v2;


use app\api\controller\v3\Wxpaymch;
use app\services\car\OrderPayServices;
use think\log;
use crmeb\services\SpreadsheetExcelService;
use app\Request;
use crmeb\services\app\MiniProgramService;
use crmeb\services\app\WechatService;
use app\api\controller\v3\WxPayController as v3WxPayController;
use app\api\controller\v3\SampleController;
use think\facade\Db;
use app\api\controller\v2\LogController;
use app\services\wechat\NotifyService;

class WxPayController
{
    private $public_key_path;//平台证书
    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->platPublicKey = public_path()."uploads/wx/pt.pem";//平台证书用于验签
    }
    /*
     * 微信支付
     * 对接约你游
     * 2024年7月18日13:40:26
     * */
    public function WeChatpay(Request $request)
    {
        $data = $request->postMore([
            ['appid','2'],//1是正式2是测试3是AI约你游4是测试AI约你游
            ['vendorid',''],//商户id
            ['order_type',''],//订单类型 1直营商户 2入驻商户
            ['pay_type',''],//支付类型 app/jsapi
            ['openid',''],//pay_type等于jsapi必传
            ['orderon',''],//订单号
            ['amount',''],//金额
            ['body',''],//订单详情
        ]);
        $log = new LogController();
        $log_id = $log->add_log($data);
        $appid = $data['appid'];//1是正式约你游环境2是测试约你游环境3是AI约你游
        if(!$appid||!$data['order_type']||!$data['pay_type']||!$data['orderon']||!$data['amount']||!$data['body']){
            return app('json')->fail('参数不完整。Incomplete parameters。');
        }
        if($data['pay_type']=='jsapi'){//******************************************小程序支付***************************************************
            if($data['order_type']==1){//直营支付
                MiniProgramService::get_vendorid($appid);
                $code=  MiniProgramService::jsPay($data['openid'], $data['orderon'], $data['amount'], "", $data['body'], "JSAPI");
            }else{//服务商jsapi支付
                if(!$data['vendorid'])app('json')->fail('服务商支付必传商户ID');
                $wx_applyment = Db::name('wx_applyment')->where('id',$data['vendorid'])->find();
                if(!$wx_applyment)app('json')->fail('服务商数据异常');
                $WxPay = new v3WxPayController();
                $code =  $WxPay->unifyPay($data['openid'], $data['orderon'], $data['amount'], $data['body'],$appid,$wx_applyment['mchid']);
            }
        }else{//******************************************APP支付***************************************************
            if($data['order_type']==1){//直营支付
                WechatService::get_vendorid($appid);
                $code = WechatService::appPay($data['openid'], $data['orderon'], $data['amount'], "", $data['body'], "APP",$appid);
            }else{//服务商app支付
                if(!$data['vendorid'])app('json')->fail('服务商支付必传商户ID');
                $wx_applyment = Db::name('wx_applyment')->where('id',$data['vendorid'])->find();
                if(!$wx_applyment)app('json')->fail('商户数据异常');
                $WxPay = new v3WxPayController();
                $code =  $WxPay->WxappPay($data['orderon'], $data['amount'], $data['body'],$appid,$wx_applyment['mchid']);
            }
            //******************************************app支付*********************************************************
        }
        if($code['package']){//package不为空说明请求成功
            $log->add_log($code,$log_id);
            return app('json')->success("请求成功",$code);
        }

    }

    /*
     * 子商户添加分账方 分账前操作
     * */
    public function addReceivers(){
        $fz = new SampleController();
        $ok = $fz->addReceivers();
    }

    /*
     * 微信支付退款
     * */
    public function WeChatpay_refund(Request $request){
        $data = $request->postMore([
            ['appid',''],//1是正式2是测试3是AI约你游
            ['vendorid',''],//商户id
            ['out_trade_no',''],//商户订单号
            ['refund_order_type',''],//退款订单类型 1服务商2直营
            ['transaction_id',''],//微信支付单号
            ['out_refund_no',''],//商户系统内部的退款单号
            ['refund',''],////退款标价金额，单位为分，可以做部分退款
            ['total',''],//订单总金额，单位为分
        ]);
        $log = new LogController();
        $log_id = $log->add_log($data);
        $appid = 2;//1是正式2是测试3是AI约你游
        if(!$data['transaction_id']||!$data['out_refund_no']||!$data['refund']||!$data['total']){
            return app('json')->fail('参数不完整,无法请求接口。Incomplete parameters Unable to initiate refund。');
        }
        if($data['refund_order_type']==1){
            $WxPay = new v3WxPayController();
            $v3_app =  $WxPay->wx_refund($data['transaction_id'], $data['total'], $data['refund'],$data['out_refund_no'],$data['vendorid']);
            if($v3_app['code']==1){
                return app('json')->success("退款成功",$v3_app);
            }
        }else{
            $opUserId = ""; $refundReason = "";$type = "out_trade_no";
            MiniProgramService::get_vendorid($appid);
            $ok = MiniProgramService::refund($data['out_trade_no'],$data['out_refund_no'],$data['total'],$data['refund'],$opUserId,$refundReason,$type);//小程序
            if($ok->return_code=="SUCCESS"&&$ok->return_msg=="OK"){
                $ok['code']  = 1;
            }
        }

    }
    /*
     * 发起分账
     * */
    public function bonus(Request $request){

        $data = $request->postMore([
            ['transaction_id',''],//【微信订单号】 微信支付订单号
            ['out_order_no',''],//【商户分账单号】 服务商系统内部的分账单号，在服务商系统内部唯一，同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@
            ['vendorid',''],//【子商户号】 微信支付分配的子商户号，即分账的出资商户号。（直连商户不需要，服务商需要）
            ['amount',''],//【分账金额】 分账金额，单位为分，只能为整数，不能超过原订单支付金额及最大分账比例金额
        ]);
        if(!$data['transaction_id']||!$data['out_order_no']||!$data['vendorid']||!$data['amount']){
            return app('json')->fail('参数不完整。Incomplete parameters。');
        }
        $fz = new SampleController();
        $ok = $fz->divide($data);
        if ($ok['state'] == 'PROCESSING' || $ok['state'] == 'FINISHED') {
            return app('json')->success("分账成功",$ok);
        }
    }

    /*
     * 分账退回
     * */
    public function return_bonus(Request $request){
        $data = $request->postMore([
            ['out_return_no',''],//【商户回退单号】 此回退单号是商户在自己后台生成的一个新的回退单号，在商户后台唯一
            ['out_order_no',''],//【商户分账单号】 商户系统内部的分账单号，在商户系统内部唯一，同一分账单号多次请求等同一次。微信分账单号和商户分账单号二选一填写 取值范围：[0-9a-zA-Z_*@-]
            ['return_mchid',''],//【回退商户号】 分账回退的出资商户，只能对原分账请求中成功分给商户接收方进行回退
            ['amount',''],//【分账金额】 分账金额，单位为分，只能为整数，不能超过原订单支付金额及最大分账比例金额
            ['vendorid',''],//【子商户号】 微信支付分配的子商户号，即分账的出资商户号。（直连商户不需要，服务商需要）
        ]);
        if(!$data['out_return_no']||!$data['out_order_no']||!$data['mchid']||!$data['amount']||!$data['vendorid']){
            return app('json')->fail('参数不完整。Incomplete parameters。');
        }
        $fz = new SampleController();
        $ok = $fz->return_divide($data);
        if ($ok['result'] == 'PROCESSING' || $ok['state'] == 'SUCCESS') {
            return app('json')->success("分账退回",$ok);
        }
    }

    /*
     * V3微信支付回调数据验签解密
     * */
    public function decrypt(Request $request){
        $data = file_get_contents('php://input');
        $data = json_decode($data,true);
        if(!$data)return app('json')->fail('参数不完整。Incomplete parameters。');
        $getCallBackJson = json_encode($data['getCallBackJson'],320);
        if(!$data['getCallBackJson']||!$data['header']){
            return app('json')->fail('参数不完整。Incomplete parameters。');
        }
        $wxpaymch = new Wxpaymch();
        $serial_no = $wxpaymch->parseSerialNo($wxpaymch->getCertFicates());
//        $header = '{"Wechatpay-Timestamp":"1723528222","Pragma":"no-cache","Wechatpay-Signature-Type":"WECHATPAY2-SHA256-RSA2048","Wechatpay-Signature":"kfpM+gqf7SYcDnWiNwy+6H\/14\/AOyqLkjI3evw12dJbYLCBDsFCUh5uZnby3cfZiPQY3djgHGVY3jLOEwC5yR3fAPpz4Xv+sIHnRBNLiatouMMe5QgWzdiINqjL1dkU1N2J7KBrYiSFlLjT\/eWHzvo0WxQuk4Qls9DSfSLHNJrfyFVJGru+ix5lUnfi98NfzUm1v9R\/clbKAePAZExWJgVhOxylOlD2J2b0DgUKQf\/J7rMbHteZyaqJU5DWVVUltMGicHcjYhWEmQu4vz+eCrrPhdJWgSjPOknw6SmUeeBG7g+TovcQNoYobizpEbO9oiOtgRyf3WDnMEF5iR4d8PA==","Wechatpay-Serial":"18E3E05261F93303D7CC79CC5159804E530A6BE4","Content-Type":"application\/json","Wechatpay-Nonce":"U1bROYbnXsQDrfbJ0qyeWYQy1O3EgRJp","Host":"tc.klch.cn","Accept":"*\/*","User-Agent":"Mozilla\/4.0","Connection":"Keep-Alive","Content-Length":"983"}';
        $header = $data['header'];
//        $getCallBackJson = '{"id":"1a4fdafe-2894-5099-ae7b-75a50e48e770","create_time":"2024-08-13T13:50:21+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"支付成功","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"JIgZxv6ayoJULSR/Arv1SHc6PfgIloVeeRJDESIHmQd1WSxEwL0A/OBgxdf/to6lkazMqrKT32dsaoIFgfZDKgASya0KuKdFqubhSjM0+EBZcQd2w385kNxh4h4J0iknBT4OJuRWDA+5z2yJb8hV7BbyOoTU41p43Xu56BE3noaEHjhXtRwdQCqTSuYBzAobSfVniVNBANcjVgvYRikGlPocKSfe2hLpTmbfNvy+eyYYjI+WKrBK0/xpcNakAHeaH/NmL6SYURdsxQDrZNdOvmEtd1y7CjEd9AnKUFLMgOA1+SoO6qbc2eMlWchyMrPuU2p2NEOOBh8ORfBvFhWlaGuZ303Ztec2Mlz59CW42Gdtm+com28pqQj/Hx3k5jyWnK6defg0jYa+ljQNEdMnQxOam4amFFR6p0pDPFDu6Y/dULB5Fdm6zRo38xtaLuGtBOt2/HkLKlslxBlLpFK4TeTvztlPheYifBbCiMcQbbn+XFRlI2MbF4KJ48q1ogPXNjn+ofrIkyC69BAPT3REfPDqX9OvjCFc8QSOWe8H62TRewsSyBVy0yUiIt5iel5Wr/3Ftq1CZ/Qfryw+C2gkXgbIXHMxpj8B1tFH2nn7JSwgkiya/qZcVqEDhfnWPS+eR9eaQ+xGBtAFSdg=","associated_data":"transaction","nonce":"7UhVfqLcnxKA"}}';
        if ($header['Wechatpay-Serial'] != $serial_no) {
            return app('json')->fail('平台证书序列号不一致，签名验证不通过');
        }
        $pub_path = $this->platPublicKey;
        $plat_cert_decrtpt = file_get_contents($pub_path);
        $pub_key = openssl_pkey_get_public($plat_cert_decrtpt);//平台公钥  重点 验签要用平台公钥
        $Signature = $header['Wechatpay-Signature'];
        $message = $header['Wechatpay-Timestamp'] . "\n" . $header['Wechatpay-Nonce'] . "\n" . $getCallBackJson . "\n";
        $sign = base64_decode($Signature);
        $ok = openssl_verify($message, $sign, $pub_key, OPENSSL_ALGO_SHA256);//回调验签
        if ($ok == 1) {
            return app('json')->success("签名验证通过");
        } else {
            return app('json')->fail('签名验证不通过');
        }

    }

    public function verify_wechatnotify($header, $response_body)
    {
        //$header 回调头部信息 //$response_body回调主体
        //获取平台证书
//        $plat = $this->get_cert();
        $wxpaymch = new Wxpaymch();
        $serial_no = $wxpaymch->parseSerialNo($wxpaymch->getCertFicates());
//        $path =  'XX/Wechat/wxp_cert.pem';//平台证书
//        $plat_cert = file_get_contents($path);
//        $plat = json_decode($plat_cert, true);
        //serial_no平台证书序列号 //跟商户证书序列号不一样 不要搞混了
        //验证回调头部信息中的平台证书序列号跟平台证书序列号是否一致
        if ($header['Wechatpay-Serial'] != $serial_no) {
            return $data=['code'=>'0','msg'=> '平台证书序列号不一致，签名验证不通过'];
        }
        //解密平台证书序列
        $associatedData = $plat['data'][0]['encrypt_certificate']['associated_data'];
        $nonceStr = $plat['data'][0]['encrypt_certificate']['nonce'];
        $ciphertext = $plat['data'][0]['encrypt_certificate']['ciphertext'];
        //官方解密文档 https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
        $plat_cert_decrtpt = $this->decryptToString($associatedData, $nonceStr, $ciphertext);//平台证书解密后即生成公钥 //这个解密方法看[官方文档](https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi)https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
        //$pub_path = 'XX/Wechat/wxp_pub.pem';
//        file_put_contents($pub_path, $plat_cert_decrtpt);//平台公钥 //保存平台公钥 回调验签要用
        //$plat_cert_decrtpt = file_get_contents($pub_path);
        $pub_key = openssl_pkey_get_public($plat_cert_decrtpt);//平台公钥
        $Signature = $header['Wechatpay-Signature'];
        $message = $header['Wechatpay-Timestamp'] . "\n" . $header['Wechatpay-Nonce'] . "\n" . $response_body . "\n";
        $sign = base64_decode($Signature);
        $ok = openssl_verify($message, $sign, $pub_key, OPENSSL_ALGO_SHA256);//回调验签
        if ($ok == 1) {
//            return $this->error('1', '回调签名验证成功');
            return 1;
        } else {
            return false;
        }
    }





}